package com.aizhixin.lab.quartz.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import com.aizhixin.lab.quartz.entity.QuartzJob;
import com.aizhixin.lab.quartz.repository.QuartzJobRepository;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Slf4j
@Service
@Transactional
public class QuartzJobService {
    @Autowired
    private QuartzJobRepository quartzJobRepository;
    @Autowired
    private Scheduler scheduler;

    /**
     * 立即执行的任务分组
     */
    private static final String JOB_TEST_GROUP = "test_group";

    public List<QuartzJob> findByJobClassName(String jobClassName) {
        return quartzJobRepository.findByJobClassName(jobClassName);
    }

    /**
     * 保存&启动定时任务
     */
    public QuartzJob saveAndScheduleJob(QuartzJob quartzJob) {
        if (0==quartzJob.getStatus()) {
            // 定时器添加
//            schedulerDelete(quartzJob.getJobClassName().trim());
            this.schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
        }
        // DB设置修改
        quartzJob.setDelFlag(0);
        quartzJob.setId(UUID.randomUUID().toString());
        return quartzJobRepository.save(quartzJob);
    }

    /**
     * 恢复定时任务
     */
    public QuartzJob resumeJob(QuartzJob quartzJob) {
        schedulerDelete(quartzJob.getJobClassName().trim());
        schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
        quartzJob.setStatus(0);
        return quartzJobRepository.save(quartzJob);
    }
    public QuartzJob  findOne(String id){
        QuartzJob one = quartzJobRepository.findOne(id);
        return one;
    }
    /**
     * 编辑&启停定时任务
     * @throws SchedulerException
     */
    public QuartzJob editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException {
        if ("0".equals(quartzJob.getStatus())) {
            schedulerDelete(quartzJob.getJobClassName().trim());
            schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
        }else{
            scheduler.pauseJob(JobKey.jobKey(quartzJob.getJobClassName().trim()));
        }
        return quartzJobRepository.save(quartzJob);
    }

    /**
     * 删除&停止删除定时任务
     */
    public QuartzJob deleteAndStopJob(QuartzJob job) {
        schedulerDelete(job.getJobClassName().trim());
        QuartzJob ok = quartzJobRepository.save(job);
        return ok;
    }

    public void execute(QuartzJob quartzJob) throws Exception {
        String jobName = quartzJob.getJobClassName().trim();
        Date startDate = new Date();
        String ymd = DateUtil.format(startDate,"yyyyMMddHHmmss");
        String identity =  jobName + ymd;
        //3秒后执行 只执行一次
        startDate.setTime(startDate.getTime()+3000L);
        // 定义一个Trigger
        SimpleTrigger trigger = (SimpleTrigger)TriggerBuilder.newTrigger()
                .withIdentity(identity, JOB_TEST_GROUP)
                .startAt(startDate)
                .build();
        // 构建job信息
        JobDetail jobDetail = JobBuilder.newJob(getClass(jobName).getClass()).withIdentity(identity).usingJobData("parameter", quartzJob.getParameter()).build();
        // 将trigger和 jobDetail 加入这个调度
        scheduler.scheduleJob(jobDetail, trigger);
        // 启动scheduler
        scheduler.start();
    }

    public void pause(QuartzJob quartzJob){
        schedulerDelete(quartzJob.getJobClassName().trim());
        quartzJob.setStatus(-1);
        quartzJobRepository.save(quartzJob);
    }


    /**
     * 添加定时任务
     *
     * @param jobClassName
     * @param cronExpression
     * @param parameter
     */
    private void schedulerAdd(String jobClassName, String cronExpression, String parameter) {
        try {
            // 启动调度器
            scheduler.start();

            // 构建job信息
//            JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName).usingJobData("parameter", parameter).build();
            String id= UUID.randomUUID().toString();
            JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(id).usingJobData("parameter", parameter).build();

            // 表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

            // 按新的cronExpression表达式构建一个新的trigger
//            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName).withSchedule(scheduleBuilder).build();
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(id).withSchedule(scheduleBuilder).build();

            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            throw new RuntimeException("创建定时任务失败", e);
        } catch (RuntimeException e) {
            throw new RuntimeException(e.getMessage(), e);
        }catch (Exception e) {
            throw new RuntimeException("后台找不到该类名：" + jobClassName, e);
        }
    }

    /**
     * 删除定时任务
     *
     * @param jobClassName
     */
    private void schedulerDelete(String jobClassName) {
        try {
            scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName));
            scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName));
            scheduler.deleteJob(JobKey.jobKey(jobClassName));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException("删除定时任务失败");
        }
    }

    private static Job getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (Job) class1.newInstance();
    }
}
